﻿using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;

namespace Padsurface.App.ViewModels
{
    public partial class PadViewModel
    {
        private CancellationTokenSource _updatePlayingTimeCancellation;

        private bool _isPlayingToggled;
        public bool IsPlayingToggled
        {
            get { return _isPlayingToggled; }
            set
            {
                SetProperty(ref _isPlayingToggled, value);
                OnPlayingToggled();
            }
        }

        private bool _isPlaying;
        public bool IsPlaying
        {
            get { return _isPlaying; }
            set { SetProperty(ref _isPlaying, value); }
        }

        private string _playingTime;
        public string PlayingTime
        {
            get { return _playingTime; }
            set { SetProperty(ref _playingTime, value); }
        }

        public bool IsLoopEnabled
        {
            get { return _song.IsLoopEnabled; }
            set 
            {
                _song.IsLoopEnabled = value;
                OnPropertyChanged();
            }
        }

        public string Bpm
        {
            get { return _song.BeatsPerMinute.ToString(); }
            set 
            {
                _song.BeatsPerMinute = double.Parse(value);
                OnPropertyChanged();
            }
        }

        private void OnPlayingToggled()
        {
            lock (_lock)
            {
                if (!IsPlaying)
                    StartPlaying();
                else
                    StopPlaying();
            }
        }

        private async void StartPlaying()
        {
            IsPlaying = true;
            
            _updatePlayingTimeCancellation = new CancellationTokenSource();
            UpdateTimer(() => PlayingTime = _song.CurrentTime.ToString(@"hh\:mm\:ss\.fff"), _updatePlayingTimeCancellation.Token);

            await _song.PlayFromStart();
        }

        private async void StopPlaying()
        {
            IsPlaying = false;
            _updatePlayingTimeCancellation.Cancel();

            await _song.Stop();

            if (IsRecordingPerformance)
                IsRecordingPerformanceToggled = false;
        }

        private async void SongStopped(object sender, EventArgs e)
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                if(IsPlaying)
                    IsPlayingToggled = false;

                if(IsRecordingPerformance)
                    IsRecordingPerformanceToggled = false;
            });
        }

        #region IncreaseBpmCommand

        public ICommand IncreaseBpmCommand { get; set; }

        private void IncreaseBpm(object obj)
        {
            ChangeBpm(+1);
        }

        private bool CanIncreaseBpm(object parameter)
        {
            return (_song.BeatsPerMinute < double.MaxValue);
        }

        #endregion

        #region DecreaseBpmCommand

        public ICommand DecreaseBpmCommand { get; set; }

        private void DecreaseBpm(object obj)
        {
            ChangeBpm(-1);
        }

        private bool CanDecreaseBpm(object parameter)
        {
            return (_song.BeatsPerMinute > 0);
        }

        #endregion

        private void ChangeBpm(int valueToAdd)
        {
            _song.BeatsPerMinute += valueToAdd;
            Bpm = _song.BeatsPerMinute.ToString();
        }
    }
}